package server.testing;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.ArrayList;

import client.management.ManagementClient;

/**
 * The class performs a load test of the auction server system, including
 * billing auctions and printing analytics. It simulates the acting of a defined
 * number of clients on the system. Configuration is stored in a
 * loadtest.properties file which must be provided. It then loggs in as a
 * management client and prints analytics from the analyticsserver.
 */
public class LoadTestingService {

	public static void main(String[] args) {
		ExecutorService loadTestClientExecutor;
		ArrayList<LoadTestingClientThread> clientThreads;
		int clientsNumber = 0, auctionsPerMin = 0, auctionDuration = 0, updateIntervalSec = 0, bidsPerMin = 0, tcpPort = 0;
		String host;
		final String analyticsBinding, billingBinding;
		// USAGE===================================================
		if (args.length != 4) {
			System.err
					.println("Usage: LoadTestingService <host> <tcpPort> <AnalyticsBindingName> <BillingBindingName>");
			System.exit(1);
		}
		try {
			tcpPort = Integer.parseInt(args[1]);
			if (tcpPort < 1 || tcpPort > 65535) {
				throw new IllegalArgumentException();
			}
		} catch (NumberFormatException e) {
			System.err
					.println("Usage: LoadTestingService <host> <tcpPort> <AnalyticsBindingName>");
			System.exit(1);
		} catch (IllegalArgumentException e2) {
			System.err.println("ERROR: TCP-Port must be between 1 and 65535.");
		}
		analyticsBinding = args[2];
		billingBinding = args[3];

		// INITIALIZATION==========================================
		loadTestClientExecutor = Executors.newCachedThreadPool();
		clientThreads = new ArrayList<LoadTestingClientThread>();
		host = args[0];
		java.io.InputStream is = ClassLoader
				.getSystemResourceAsStream("./loadtest.properties");
		if (is != null) {
			java.util.Properties props = new java.util.Properties();
			try {
				props.load(is);
				clientsNumber = Integer.parseInt(props.getProperty("clients"));
				auctionsPerMin = Integer.parseInt(props
						.getProperty("auctionsPerMin"));
				auctionDuration = Integer.parseInt(props
						.getProperty("auctionDuration"));
				updateIntervalSec = Integer.parseInt(props
						.getProperty("updateIntervalSec"));
				bidsPerMin = Integer.parseInt(props.getProperty("bidsPerMin"));
			} catch (IOException e) {
				e.printStackTrace();
			} catch (NumberFormatException e) {
				System.err
						.println("ERROR: Values in loadtest.properties file are no integers!");
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else {
			System.err.println("Properties file not found!");
		}

		// LOAD TEST==========================================
		System.out.println("LOAD TESTING:");
		Thread managementThread = new Thread() {

			/*
			 * (non-Javadoc)
			 * 
			 * @see java.lang.Thread#run()
			 */
			@Override
			public void run() {
				ManagementClient.main(new String[] { analyticsBinding,
						billingBinding, "loadTestUserPass" });
			}
		};
		managementThread.start();
		for (int i = 0; i < clientsNumber; i++) {
			LoadTestingClientThread client = new LoadTestingClientThread(host,
					tcpPort, auctionsPerMin, auctionDuration,
					updateIntervalSec, bidsPerMin);
			clientThreads.add(client);
			loadTestClientExecutor.submit(client);
		}
		try {
			managementThread.join();
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		loadTestClientExecutor.shutdownNow();
		for (LoadTestingClientThread thread : clientThreads) {
			thread.shutDown();
		}
	} // end of main
} // end of class
